package com.flyco.modules.stm.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.AbstractChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.flyco.common.constant.StockConstant;
import com.flyco.common.exception.FlycoException;
import com.flyco.common.util.oConvertUtils;
import com.flyco.modules.oms.entity.OmsOrderTrace;
import com.flyco.modules.pms.mapper.PmsSkuStockMapper;
import com.flyco.modules.pms.vo.PmsProductSkuVO;
import com.flyco.modules.stm.entity.StmStock;
import com.flyco.modules.stm.entity.StmStockRecord;
import com.flyco.modules.stm.mapper.StmStockMapper;
import com.flyco.modules.stm.mapper.StmStockRecordMapper;
import com.flyco.modules.stm.service.IStmStockService;
import com.flyco.modules.stm.vo.StmStockEditVO;
import com.flyco.modules.stm.vo.StmStockVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 门店库存
 * @Author: flyco
 * @Date: 2020-10-20
 * @Version: V1.0
 */
@Slf4j
@Service
public class StmStockServiceImpl extends ServiceImpl<StmStockMapper, StmStock> implements IStmStockService {

    @Autowired
    private StmStockMapper stmStockMapper;
    @Autowired
    private StmStockRecordMapper stmStockRecordMapper;
    @Autowired
    private PmsSkuStockMapper pmsSkuStockMapper;
    @Autowired
    private IStmStockService stmStockService;

    @Override
    @Transactional
    public void stockInOut(List<StmStockVO> stockVOList, Long storeId, String inoutType, String bizType,
                           String sourceType, String sourceId, String changeReason) {
        Map<Long, List<StmStockVO>> voMap = stockVOList.stream().collect(Collectors.groupingBy(e -> e.getProductId()));
        Set<Long> productIds = stockVOList.stream().map(q -> q.getProductId()).collect(Collectors.toSet());
        LambdaQueryWrapper<StmStock> stockQuery = new LambdaQueryWrapper();
        stockQuery.eq(StmStock::getStoreId, storeId)
                .in(StmStock::getProductId, productIds)
                .orderByAsc(StmStock::getId);
        List<StmStock> stmStockList = this.list(stockQuery);
        List<Long> stockProductIds = stmStockList.stream().map(q -> q.getProductId()).collect(Collectors.toList());
        if (oConvertUtils.isEmpty(stockProductIds)) {
            stmStockList.addAll(stmStockService.initStmStock(storeId, productIds));
        } else if (oConvertUtils.isNotEmpty(stockProductIds) && productIds.size() > stockProductIds.size()) {
            productIds.removeAll(stockProductIds);
            stmStockList.addAll(stmStockService.initStmStock(storeId, productIds));
        }
        List<StmStockEditVO> editVOS = new ArrayList<>();
        stmStockList.forEach(stock -> {
            StmStockEditVO vo = new StmStockEditVO();
            vo.setId(stock.getId());
            vo.setStock(0);
            vo.setSampleStock(0);
            vo.setLossStock(0);
            vo.setInnerStock(0);
            vo.setGiftStock(0);
            vo.setDiffStock(0);
            List<StmStockVO> stockVOS = voMap.get(stock.getProductId());
            Set<String> stockTypes = stockVOS.stream().map(q -> q.getStockType()).collect(Collectors.toSet());

            stockVOS.forEach(stockVO -> {
                switch (stockVO.getStockType()) {
                    case StockConstant.STOCK_TYPE_GOODS:
                        vo.setStock(vo.getStock() + getStockQty(stockVO, inoutType));
                        break;
                    case StockConstant.STOCK_TYPE_GIFT:
                        vo.setGiftStock(vo.getGiftStock() + getStockQty(stockVO, inoutType));
                        break;
                    case StockConstant.STOCK_TYPE_DIFF:
                        vo.setDiffStock(vo.getDiffStock() + getStockQty(stockVO, inoutType));
                        break;
                    case StockConstant.STOCK_TYPE_INNER:
                        vo.setInnerStock(vo.getInnerStock() + getStockQty(stockVO, inoutType));
                        break;
                    case StockConstant.STOCK_TYPE_LOSS:
                        vo.setLossStock(vo.getLossStock() + getStockQty(stockVO, inoutType));
                        break;
                    case StockConstant.STOCK_TYPE_SAMPLE:
                        vo.setSampleStock(vo.getSampleStock() + getStockQty(stockVO, inoutType));
                        break;
                    default:
                        //如果不存在，暂时选择放弃，以后看情况报个错
                        break;
                }
            });
            List<StmStockRecord> records = new ArrayList<>();
            stockTypes.forEach(stockType -> {
                records.add(createRecord(stock, vo, storeId, inoutType, stockType, bizType, sourceType, sourceId, changeReason));
            });
            int update = 0;
            if (Objects.equals(StockConstant.STOCK_OUT_TYPE_SALE, bizType))
                update = stmStockMapper.editStockWithSales(vo);
            else
                update = stmStockMapper.editStock(vo);
            log.info("更新库存数量:" + update);
            if (update > 0) {
                records.forEach(r -> {
                    stmStockRecordMapper.insert(r);
                });
            } else {
                throw new FlycoException("库存修改失败，请查看库存数量再操作");
            }
        });
    }

    private Integer getStockQty(StmStockVO stockVO, String inoutType) {
        if (Objects.equals(inoutType, StockConstant.STOCK_OUT)) {
            return -stockVO.getProductQty();
        } else {
            return stockVO.getProductQty();
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public List<StmStock> initStmStock(Long storeId, Set<Long> productIds) {
        List<StmStock> stmStocks = new ArrayList<>();
        List<PmsProductSkuVO> skuVOS = pmsSkuStockMapper.getProductSkuList();
        Map<Long, List<PmsProductSkuVO>> skuVOMap = skuVOS.stream().collect(Collectors.groupingBy(e -> e.getId()));
        productIds.forEach(productId -> {
            StmStock stock = new StmStock();
            stock.setStoreId(storeId);
            stock.setProductId(productId);
            if (skuVOMap.containsKey(productId)) {
                PmsProductSkuVO vo = skuVOMap.get(productId).get(0);
                stock.setProductSn(vo.getProductSn());
                stock.setSkuCode(vo.getSkuCode());
            }
            stmStockMapper.insert(stock);
            log.info("初始化库存记录：" + stock.getId());
            stmStocks.add(stock);
        });
        return stmStocks;
    }

    /**
     * 创建库存改动流水对象
     *
     * @param stock
     * @param editVO
     * @param inoutType
     * @param stockType
     * @param bizType
     * @param sourceType
     * @param sourceId
     * @param changeReason
     * @return
     */
    private StmStockRecord createRecord(StmStock stock, StmStockEditVO editVO, Long storeId, String inoutType, String stockType,
                                        String bizType, String sourceType, String sourceId, String changeReason) {
        StmStockRecord record = new StmStockRecord();
        record.setStoreId(storeId);
        record.setProductId(stock.getProductId());
        record.setProductSn(stock.getProductSn());
        record.setStockId(stock.getId());
        record.setSkuCode(stock.getSkuCode());
        switch (stockType) {
            case StockConstant.STOCK_TYPE_GOODS:
                record.setQuantity(Math.abs(editVO.getStock()));
                record.setOldStock(stock.getStock());
                break;
            case StockConstant.STOCK_TYPE_GIFT:
                record.setQuantity(Math.abs(editVO.getGiftStock()));
                record.setOldStock(stock.getGiftStock());
                break;
            case StockConstant.STOCK_TYPE_DIFF:
                record.setQuantity(Math.abs(editVO.getDiffStock()));
                record.setOldStock(stock.getDiffStock());
                break;
            case StockConstant.STOCK_TYPE_INNER:
                record.setQuantity(Math.abs(editVO.getInnerStock()));
                record.setOldStock(stock.getInnerStock());
                break;
            case StockConstant.STOCK_TYPE_LOSS:
                record.setQuantity(Math.abs(editVO.getLossStock()));
                record.setOldStock(stock.getLossStock());
                break;
            case StockConstant.STOCK_TYPE_SAMPLE:
                record.setQuantity(Math.abs(editVO.getSampleStock()));
                record.setOldStock(stock.getSampleStock());
                break;
            default:
                //如果不存在，暂时选择放弃，以后看情况报个错
                break;
        }
        record.setInoutType(inoutType);
        record.setStockType(stockType);
        record.setBizType(bizType);
        record.setSourceType(sourceType);
        record.setSourceId(sourceId);
        record.setChangeReason(changeReason);
        record.setVersion(0);
        return record;
    }


    @Override
    public Page<StmStock> getStockPage(Page<StmStock> page, Wrapper<StmStock> wrapper) {
        return page.setRecords(stmStockMapper.getStockPage(page, wrapper));
    }

}
